#region Using directives

using System;
using System.Text;
using System.Reflection;
using System.Collections.Generic;

using Weazel.Gezel.Model;

#endregion



namespace Weazel.Gezel.Simulator.Reference
{
  /// <summary>
  /// Controls the creation of IP-blocks
  /// </summary>
  static class IpBlockFactory
  {
    private static Dictionary<string, Type> ipTypes;

    /// <summary>
    /// Static constructor which detects ipblocks
    /// contained in this assembly at load time
    /// </summary>
    static IpBlockFactory()
    {
      ipTypes = new Dictionary<string, Type>();

      Assembly ass = Assembly.GetExecutingAssembly();
      Type[] types = ass.GetTypes();
      foreach (Type type in types)
      {
        if (type.IsSubclassOf(typeof(AbstractIpBlock)))
        {
          object[] attrs = type.GetCustomAttributes(true);
          if (attrs.Length == 1 && attrs[0] is IpBlockAttribute)
          {
            ipTypes.Add((attrs[0] as IpBlockAttribute).IpType, type);
          }
        }
      }
    }

    /// <summary>
    /// Returns an instance of the ipblock of the
    /// specified type
    /// </summary>
    /// <param name="ipblock"></param>
    /// <returns></returns>
    public static AbstractIpBlock Create(IPBlock ipblock, Simulation simulation)
    {
      string iptype = ipblock.IpType;
      if (ipTypes.ContainsKey(iptype))
      {
        // call the version of create instance with many arguments
        // in order to specify constructor arguments (a string)
        AbstractIpBlock aip = (AbstractIpBlock)Assembly.GetExecutingAssembly().CreateInstance(
          ipTypes[iptype].FullName, 
          false, 
          BindingFlags.Default, 
          null, 
          new object[] { ipblock.Name }, 
          null, 
          new object[0]
        );

				// add reference to output writer
				aip.OutputBuffer = simulation.buffer;

				return aip;
      }
      else
        throw new UnknownIpBlockException(ipblock);
    }
  }
}
